﻿/*
 *  Ps3RemoteSleep is a workaround to place the Sony Playstation 3 (PS3) Blu-ray Remote Control in sleep/sniff mode 
 *  using the integrated Microsoft Bluetooth stack. For use with EventGhost/XBMC Windows 7 32/64 compatible.
 *  
 *  This application should be run as an Administrator or ideally UAC should be disabled so that the Ps3RemoteSleep can be
 *  started at Windows logon.
 *  
 *  InTheHand.Net.Personal is the primary library of the 32feet.NET project located on codeplex: http://32feet.codeplex.com/
 *  
 *  To put the remote a sleep, I use a rather crude method. Normally, the Playstation 3 will send some or other sleep command 
 *  to the remote, but unfortunately someone has yet to figure out how to do this using the Microsoft Bluetooth stack since
 *  it seems to be a low level Bluetooth command.
 *  
 *  The workaround I use is to disable the Human Interface Device Bluetooth service of the remote control and then re-enable it.
 *  The unfortunate side effect of this operation is that Windows redetects the device and plays its Hardware Removal and 
 *  Insertion sounds. The workaround here was to blank the registry keys for the Windows sounds for Hardware Removal and Hardware
 *  Insertion and then place them back after delaying for about a second.
 *  
 *  Another side effect is the Device Driver Installation balloon popup in the system tray that shows up during the process. Although
 *  I did identify the registry key where the tray icon notifications control can be modified, modifications are only effective after 
 *  a restart (or shell restart) and there isn't an API to control this. The only workaround if this bothers you is to set the driver
 *  installation tray icon to "Hide icon and notifications".
 *  
 *  The last side effect is that the entire process takes some time. The Bluetooth device discovery takes a few seconds, checking if 
 *  the device is already hiberated takes about 2-5 seconds, disabling and re-enabling takes a bit, and then I delay for about a 
 *  second to wait for Windows to detect the change and "play" the hardware sounds. After all of this, the sounds are restored back 
 *  to the registry, and the application closes.
 *  
 *  Results: After removing and reconnecting the batteries or pressing the PS button for about 5 seconds, the device is in a sleep state
 *  and the current draw is about 19uA. When a button on the remote is pressed, current jumps to 19-22mA and stays there until the remote
 *  is disconnected or hibernated again. Using Ps3RemoteSleep, the current draw is identical.
 *  
 *  Subsequent version will probably be more configurable using more command line arguments.
 *  
 *  Command Line arguments:
 *  /log    Shows the log window and waits for the user to close the application.
 *  
 */


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Ps3RemoteSleep
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Shown(object sender, EventArgs e)
        {
            try
            {
                Ps3RemoteSleepClass sleep = new Ps3RemoteSleepClass();
                sleep.OnEvent += (from, args) =>
                    {
                        this.Invoke((MethodInvoker)delegate
                        {
                            lvLog.Items.Add(DateTime.Now.ToLongTimeString()).SubItems.Add(args.EventText);
                            Application.DoEvents();
                        });
                    };

                bool result = sleep.HibernateRemote();
                lvLog.Items.Add(DateTime.Now.ToLongTimeString()).SubItems.Add("Completed OK: "+(result ? "Yes" : "No"));
            }
            catch (Exception ex)
            {
                MessageBox.Show("The following exception occurred: \r\n\r\n" + ex.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
}
